package com.sztx.pay.center.rpc.component;

import java.util.Date;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.mortbay.log.Log;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONObject;
import com.sztx.pay.center.common.util.Constance;
import com.sztx.pay.center.common.util.Constance.BaseBusinessStatus;
import com.sztx.pay.center.common.util.Constance.BindCardType;
import com.sztx.pay.center.common.util.Constance.CallBackOrderState;
import com.sztx.pay.center.common.util.Constance.CardActType;
import com.sztx.pay.center.common.util.Constance.CardType;
import com.sztx.pay.center.common.util.Constance.DistributeType;
import com.sztx.pay.center.common.util.Constance.IdCardType;
import com.sztx.pay.center.common.util.Constance.PayFlowState;
import com.sztx.pay.center.common.util.Constance.PayFlowType;
import com.sztx.pay.center.common.util.Constance.TradeMessageType;
import com.sztx.pay.center.common.util.Constance.TradeOrderType;
import com.sztx.pay.center.common.util.Constance.TransferBusinessID;
import com.sztx.pay.center.common.util.Constance.TransferOrderState;
import com.sztx.pay.center.common.util.Constance.TransferType;
import com.sztx.pay.center.common.util.Constance.UserActType;
import com.sztx.pay.center.common.util.JFUtils;
import com.sztx.pay.center.common.util.ValidateUtil;
import com.sztx.pay.center.common.yhbf.YHBFSensitiveEnc;
import com.sztx.pay.center.core.service.AccountService;
import com.sztx.pay.center.core.service.ActService;
import com.sztx.pay.center.core.service.BillnoService;
import com.sztx.pay.center.core.service.CallBackService;
import com.sztx.pay.center.core.service.MqMessageService;
import com.sztx.pay.center.core.service.OrderMappingService;
import com.sztx.pay.center.core.service.PayCoreCallBack;
import com.sztx.pay.center.core.service.PayCoreService;
import com.sztx.pay.center.core.service.SettleService;
import com.sztx.pay.center.core.service.UserInfoService;
import com.sztx.pay.center.core.service.bean.CallBackInfo;
import com.sztx.pay.center.core.service.bean.PayCoreAccountInfo;
import com.sztx.pay.center.core.service.bean.PayCoreDistribute;
import com.sztx.pay.center.core.service.bean.PayCoreRefund;
import com.sztx.pay.center.core.service.bean.PayCoreResult;
import com.sztx.pay.center.core.service.bean.PayCoreTradeInfo;
import com.sztx.pay.center.core.service.bean.PayCoreTransferReq;
import com.sztx.pay.center.core.service.bean.PayCoreTransferResult;
import com.sztx.pay.center.core.service.bean.TradeInfo;
import com.sztx.pay.center.core.service.util.SettleTradeType;
import com.sztx.pay.center.core.service.util.SettleType;
import com.sztx.pay.center.core.service.util.TranType;
import com.sztx.pay.center.dataaccess.dao.mysql.OrderTransferMysqlDAO;
import com.sztx.pay.center.dataaccess.dao.redis.LockRedisDAO;
import com.sztx.pay.center.dataaccess.domain.OrderTransferDO;
import com.sztx.pay.center.dataaccess.domain.UserActDO;
import com.sztx.pay.center.dataaccess.domain.UserBindCardDO;
import com.sztx.pay.center.dataaccess.domain.UserInfoDO;
import com.sztx.pay.center.rpc.api.domain.TradeBaseRequest;
import com.sztx.pay.center.rpc.api.domain.TradeFlowMessage;
import com.sztx.pay.center.rpc.api.domain.TradeResponse;
import com.sztx.pay.center.rpc.api.domain.TransferRequest;
import com.sztx.pay.risk.rpc.api.domain.TradeType;
import com.sztx.se.common.exception.BusinessException;
import com.sztx.se.common.util.StringUtil;
/**
 *    转账
   
   1、充值
   2、转账（个人账户A转入个人账户B） C2C
   3、代发
   
		TRAN_BANLANCE_TO_BANLANCE
		子流程为：2
		
		TRAN_BANLANCE_TO_BANK
		子流程为：2,3
		
		TRAN_BANK_TO_BANLANCE
		子流程为：1，2
		
		TRAN_BANK_TO_BANK
		子流程为：1，3
 * @author LEIQ
 *
 */
public class TradeTransferSrervice extends TradeService implements PayCoreCallBack{
	private long payAmount;//实际转账金额
	private TransferType transferType;//转账类型
	private SettleTradeType settleTradeType;//结算类型
	private boolean isPassClipherPay;//快捷支付是否支持免短信支付（true 是  false 不是  默认 否）
	
	OrderTransferMysqlDAO orderTransferMysqlDAO;

	AccountService accountService;
	
	BillnoService billnoService;
	
	PayCoreService payCoreService;
	
	SettleService settleService;
	
	@Autowired
	CallBackService callBackService;
	
	@Autowired
	OrderMappingService orderMappingService;
	@Autowired
	private LockRedisDAO lockRedisDAO;
	@Autowired
	private ActService actService;
	@Autowired
	private UserInfoService userInfoService;
	@Autowired
	private MqMessageService mqMessageService;
	@Override
	void checkPrivateParam(Map<String, String> params) {
		String payerUserId = params.get("payerUserId");
		String payeeUserId = params.get("payeeUserId");
		String payType = params.get("payType");
		String receiverType = params.get("receiverType");
		String amount = params.get("amount");
		String bindNo = params.get("bindNo");
		String cardHolder = params.get("cardHolder");
		String cardNo = params.get("cardNo");
		String bankId = params.get("bankId");
		String cardActType = params.get("cardActType");
		String cardProvince = params.get("cardProvince");
		String cardCity = params.get("cardCity");
		
		String channelId = params.get("channelId");
		String businessType = params.get("businessType");
		String notifyUrl = params.get("notifyUrl");
		
		ValidateUtil.isNotBlank(channelId, "channelId不能为空");
		ValidateUtil.isNotBlank(businessType, "businessType不能为空");
		ValidateUtil.isNotBlank(payerUserId, "payeeUserId不能为空");
		ValidateUtil.isNotBlank(payeeUserId, "payeeUserId不能为空");
		ValidateUtil.isNotBlank(payType, "payType不能为空");
		ValidateUtil.isNotBlank(receiverType, "receiverType不能为空");
		ValidateUtil.isNotBlank(amount, "amount不能为空");
		
		if(payType.equals("2") && receiverType.equals("2")){
			throw new BusinessException("暂不支持银行卡转账到银行卡");
		}
		if(!(payType.equals("1") && receiverType.equals("1")) && StringUtil.isBlank(notifyUrl)){
			throw new BusinessException("notifyUrl不能为空");
		}
		
		
		
		//付款类别：1余额支付  2快捷支付 
		if(payType.equals("2")){
			ValidateUtil.isNotBlank(bindNo,"bindNo不能为空");
			ValidateUtil.strEqualLen(bindNo, 8, "bindNo格式不正确");
		}else {
			params.put("bindNo", null); //余额支付将bindNo置空
		}
		
		
		if(receiverType.equals("2")){
			ValidateUtil.isNotBlank(cardHolder,"cardHolder不能为空");
			ValidateUtil.isNotBlank(cardNo,"cardNo不能为空");
			//ValidateUtil.isNotBlank(bankId,"bankId不能为空");
			ValidateUtil.isNotBlank(cardActType,"cardActType不能为空");
			if(cardActType.equals("2")){
				ValidateUtil.isNotBlank(cardProvince,"cardProvince不能为空");
				ValidateUtil.isNotBlank(cardCity,"cardCity不能为空");
			}else {
				params.put("cardProvince", null);
				params.put("cardCity", null);
			}
		}else{
			params.put("cardHolder", null);
			params.put("cardNo", null);
			params.put("bankId", null);
			params.put("cardActType", null);
			params.put("cardProvince", null);
			params.put("cardCity", null);		
		}
	}

	public OrderTransferMysqlDAO getOrderTransferMysqlDAO() {
		return orderTransferMysqlDAO;
	}

	public void setOrderTransferMysqlDAO(OrderTransferMysqlDAO orderTransferMysqlDAO) {
		this.orderTransferMysqlDAO = orderTransferMysqlDAO;
	}

	public AccountService getAccountService() {
		return accountService;
	}

	public void setAccountService(AccountService accountService) {
		this.accountService = accountService;
	}

	public BillnoService getBillnoService() {
		return billnoService;
	}

	public void setBillnoService(BillnoService billnoService) {
		this.billnoService = billnoService;
	}

	public PayCoreService getPayCoreService() {
		return payCoreService;
	}

	public void setPayCoreService(PayCoreService payCoreService) {
		this.payCoreService = payCoreService;
	}

	public SettleService getSettleService() {
		return settleService;
	}

	public void setSettleService(SettleService settleService) {
		this.settleService = settleService;
	}


	@Override
	boolean isRepeatOrder(Map<String, String> params) {
		String orderId = params.get("orderId");
		
		//先从redis判断是否存在订单号
		boolean flag = lockRedisDAO.lockOrder(orderId, "", "checkRepeat");
		if(!flag){
			return true;
		}
		
		OrderTransferDO orderTransferDO = orderTransferMysqlDAO.findByOrderId(orderId);
		if (orderTransferDO != null) {
			return true;
		}
		return false;
	}

	@Override
	String recordOrder(TradeBaseRequest request) {
		if (!(request instanceof TransferRequest)) {
			logger.error("请求参数错误request不是TransferRequest对象");
			throw new BusinessException("服务器正忙，请稍后再试");
		}		
		TransferRequest transferRequest = (TransferRequest) request;
		int amount = Integer.parseInt(transferRequest.getAmount());
		String attach = transferRequest.getAttach();
		String bankId = transferRequest.getBankId();
		String bindNo = transferRequest.getBindNo();
		String cardActType = transferRequest.getCardActType();
		String cardCity = transferRequest.getCardCity();
		String cardHolder = transferRequest.getCardHolder();
		String cardNo = transferRequest.getCardNo();
		String cardProvince = transferRequest.getCardProvince();
		String expireTime = transferRequest.getExpireTime();
		String orderId = transferRequest.getOrderId();
		String payeeUserId = transferRequest.getPayeeUserId();
		String payerUserId = transferRequest.getPayerUserId();
		int payType = transferRequest.getPayType();
		int receiverType = transferRequest.getReceiverType();
		String srcChannel = transferRequest.getSrcChannel();
		String srcIp = transferRequest.getSrcIp();
		String notifyUrl = transferRequest.getNotifyUrl();
		String returnUrl = transferRequest.getReturnUrl();
		Byte transferType = (byte)getTransferType(payType, receiverType).getCode();
		this.isPassClipherPay = transferRequest.isPassClipherPay();
		
		String platChannelId = transferRequest.getChannelId();
		String businessType = transferRequest.getBusinessType();
		
		String isUsePwdStr = transferRequest.getIsUsePwd();
		Byte isUsePwd = (isUsePwdStr != null && "1".equals(isUsePwdStr)) ? new Byte("1") : new Byte("2");
		
		//生成转账订单号
		String transferOrderId = billnoService.nextTransferNo();
		//查询手续费
		SettleType settleType = null;
		if(this.transferType == TransferType.TRAN_BANK_TO_BANLANCE){
			settleType = SettleType.NOW;
		}else if(this.transferType == TransferType.TRAN_BANLANCE_TO_BANLANCE){
			settleType = SettleType.NOW;
		}else if(this.transferType == TransferType.TRAN_BANLANCE_TO_BANK){
			settleType = SettleType.LATTER;
		}else if(this.transferType == TransferType.TRAN_BANK_TO_BANK){
			settleType = SettleType.LATTER;
		}
		
		
		if(this.transferType == TransferType.TRAN_BANK_TO_BANK){
			throw new BusinessException("系统暂不支持银行卡转银行卡交易");
		}
		
		CardType cardType = null;
		if(payerBindCardInfo != null && payerBindCardInfo.getCardType() != null){
			cardType = CardType.valueOf(payerBindCardInfo.getCardType());
		}
		
		long calculateHandlingFee = settleService.calculateHandlingFee(this.settleTradeType, settleType, payerUserId, (long)amount,platChannelId,bankId,cardType);
		
		if(amount <= calculateHandlingFee){
			throw new BusinessException("手续费不能大于、等于交易金额");
		}
		
		long payAmount = (long) amount - calculateHandlingFee;
		this.payAmount = payAmount;
		//查询提现卡信息
		if(payType == 2 && payerBindCardInfo == null){
			logger.error("当前用户未绑定银行卡,payerBindCardInfo为null");
			throw new BusinessException("当前用户未绑定银行卡");
		}

		OrderTransferDO orderTransferDO = new OrderTransferDO();
		
		orderTransferDO.setAddTime(new Date());
		orderTransferDO.setPayChannelId(Constance.CHANNEL_ID_SZTF);
		orderTransferDO.setCreateTime(new Date());
		orderTransferDO.setInnerStatus(1);
		orderTransferDO.setNotifyUrl(notifyUrl);
		orderTransferDO.setOrderId(orderId);
		orderTransferDO.setPayAmount(payAmount);
		orderTransferDO.setPayeeUserAct(payeeActInfo.getActNo() );
		orderTransferDO.setPayeeUserId(payeeUserId);
		orderTransferDO.setPayerUserAct(payerActInfo.getActNo());
		orderTransferDO.setPayerUserId(payerUserId);
		orderTransferDO.setRemark(attach);
		orderTransferDO.setReturnUrl(returnUrl);
		orderTransferDO.setSourceIp(srcIp);
		orderTransferDO.setTransferAmount((long) amount);
		orderTransferDO.setTransferChannel((byte) Integer.parseInt(srcChannel));
		orderTransferDO.setTransferFee(calculateHandlingFee);
		orderTransferDO.setTransferOrderId(transferOrderId);
		orderTransferDO.setOrderStatus((byte) Constance.TransferOrderState.TRAN_STATUS_INIT.getCode());
		orderTransferDO.setOrderDesc(Constance.TransferOrderState.TRAN_STATUS_INIT.getDesc());
		
		orderTransferDO.setTransferType(transferType);
		orderTransferDO.setPayeeCardNo(YHBFSensitiveEnc.sensitiveEnc(cardNo,"cardno"));
		orderTransferDO.setIsUsePwd(isUsePwd);
		if (StringUtil.isNotBlank(cardActType)) {
			orderTransferDO.setPayeeCardactType((byte)Integer.parseInt(cardActType));
		}
	
		//orderTransferDO.setCardHolder(YHBFSensitiveEnc.sensitiveEnc(cardHolder, "realname"));
		orderTransferDO.setPayeeCardHolder(cardHolder);
		orderTransferDO.setPayBankId(bankId);
		orderTransferDO.setPayeeCardProvince(cardProvince);
		orderTransferDO.setPayeeCardCity(cardCity);
		orderTransferDO.setPayerBindNo(bindNo);
		
		orderTransferDO.setPlatChannelId(platChannelId);
		orderTransferDO.setBusinessType(businessType);
		
		orderTransferMysqlDAO.save(orderTransferDO);
		
		return transferOrderId;
	}

	
	@Override
	UserBindCardDO getPayerBindInfo(Map<String, String> params) {
		String bindNo = params.get("bindNo");
		String payerUserId = params.get("payerUserId");
//		String payType = params.get("payType");
		String channelId = params.get("channelId");
		UserBindCardDO userBindCardDO = accountService.findUserBindInfo(bindNo, payerUserId, BindCardType.BIND_QUICK_PAY);
		if(userBindCardDO == null){
			throw new BusinessException("未查询到绑定号【"+bindNo+"】相关信息");
		}
		if(userBindCardDO.getCardType() == Constance.CardType.CARD_CREDIT.getValue() && !JFUtils.isJFChannel(channelId)) {
			throw new BusinessException("当前渠道不允许使用信用卡支付");
		}
		
		return userBindCardDO;
	}

	@Override
	UserBindCardDO getPayeeBindInfo(Map<String, String> params) {
//		String receiverType = params.get("receiverType");
		
		return null;
	}

	@Override
	UserActDO getPayerActInfo(TradeBaseRequest request) {
		if (!(request instanceof TransferRequest)) {
			logger.error("请求参数错误request不是TransferRequest对象");
			throw new BusinessException("服务器正忙，请稍后再试");
		}		
		TransferRequest transferRequest = (TransferRequest) request;
		String payerUserId = transferRequest.getPayerUserId();	
		String channelId = transferRequest.getChannelId();
		Integer payerActType = transferRequest.getPayerActType();
		if(payerActType != null){
			return getPayActInfo(payerUserId, payerActType, true);
		}else{
			return getPayActInfo(payerUserId, channelId,true);
		}
		
	}
	
	
	private UserActDO getPayActInfo(String payUserId,String channelId,boolean isPayer){
		UserActDO userActDO = null;
		UserInfoDO userInfoDO = userInfoService.findUserInfo(payUserId);
		if(userInfoDO == null){
			throw new BusinessException("帐号【"+payUserId+"】不存在");
		}
		
		Integer userType = userInfoDO.getUserType();

		boolean isJfChannel = JFUtils.isJFChannel(channelId);
		
		boolean isJfUser = (userType.intValue() & Constance.UserType.AGENT.getCode()) != 0;
		boolean isSZTXUser = (userType.intValue() & Constance.UserType.SZTX.getCode()) != 0;
		
		
		if(isJfChannel && !isSZTXUser){
			//是缴费商用户
			if(!isJfUser){
				throw new BusinessException("帐号【"+payUserId+"】暂不支持此交易");
			}
			//userActDO = actService.findUserAct(payUserId, UserActType.JF);
			userActDO = actService.findValidActInfo(payUserId, UserActType.JF, isPayer);
		}else{
			//其他类型用户
			//userActDO = actService.findUserAct(payUserId, UserActType.CASH);
			userActDO = actService.findValidActInfo(payUserId, UserActType.CASH, isPayer);
		}
		if (userActDO == null) {
			throw new BusinessException(payUserId+"账户不存在");
		}
		userActDO.setUserType(userType);
		return userActDO;
	}
	private UserActDO getPayActInfo(String payUserId,Integer actType,boolean isPayer){
		UserActDO userActDO = null;
		UserActType userActType = UserActType.valueOf(actType);
		if(userActType == null){
			throw new BusinessException("actType不能为:"+actType);
		}
		userActDO = actService.findValidActInfo(payUserId, userActType, isPayer);

		if (userActDO == null) {
			throw new BusinessException(payUserId+"账户不存在");
		}
		return userActDO;
	}
	

	@Override
	UserActDO getPayeeActInfo(TradeBaseRequest request) {
		if (!(request instanceof TransferRequest)) {
			logger.error("请求参数错误request不是TransferRequest对象");
			throw new BusinessException("服务器正忙，请稍后再试");
		}		
		TransferRequest transferRequest = (TransferRequest) request;
		String payeeUserId = transferRequest.getPayeeUserId();	
		String channelId = transferRequest.getChannelId();
		Integer payeeActType = transferRequest.getPayeeActType();
		
		boolean isPayer = false;
		int transferType = getTransferType(transferRequest.getPayType(), transferRequest.getReceiverType()).getCode();
		TransferType tranType = TransferType.valueOf(transferType);
		if(tranType == TransferType.TRAN_BANK_TO_BANK || tranType == TransferType.TRAN_BANLANCE_TO_BANK){
			isPayer = true;
		}
		
		if(payeeActType != null){
			return getPayActInfo(payeeUserId, payeeActType, isPayer);
		}else{
			return getPayActInfo(payeeUserId, channelId,isPayer);
		}
	}

	@Override
	@Transactional
	TradeResponse invokePayCore(Map<String, String> params) {
		String tradeOrderId = params.get("tradeOrderId");
		String routeNo = params.get("routeNo");
		String gateWayChannelId = params.get("gateWayChannelId");
		updateTranOrderState(tradeOrderId, TransferOrderState.TRAN_STATUS_IN);
		
		OrderTransferDO orderTransferDO = orderTransferMysqlDAO.findById(tradeOrderId);
		byte tranferType = orderTransferDO.getTransferType();
		TransferType tranType = TransferType.valueOf(tranferType);
		
		PayCoreResult result = null;
		PayCoreResult withdrawresult = null;
		TradeResponse resonse = new TradeResponse();
		switch (tranType) {
		case TRAN_BANLANCE_TO_BANLANCE:
			c2cTansfer(orderTransferDO,true);
			callBack(tradeOrderId, TransferOrderState.TRAN_STATUS_SUCCESS,"SUCCESS");
			updateTranOrderState(tradeOrderId, TransferOrderState.TRAN_STATUS_SUCCESS);
			resonse.setResultCode(String.valueOf(PayFlowState.SUCCESS.getCode()));
			resonse.setResultMsg(PayFlowState.SUCCESS.getDesc());
			
			updatePayChannelId(orderTransferDO, Constance.CHANNEL_ID_SZTX);
			break;
		case TRAN_BANLANCE_TO_BANK:
			c2cTansfer(orderTransferDO,false);
			withdrawresult = innerWithDraw(orderTransferDO);
			resonse.setResultCode(String.valueOf(withdrawresult.getTradeSataus()));
			resonse.setResultMsg(withdrawresult.getTradeDesc());
			break;
		case TRAN_BANK_TO_BANK:
			result = innerCharge(orderTransferDO,gateWayChannelId,routeNo);
			if(resolveResult(result)){
				c2cTansfer(orderTransferDO,false);
				withdrawresult = innerWithDraw(orderTransferDO);
				resonse.setResultCode(String.valueOf(result.getTradeSataus()));
				resonse.setResultMsg(result.getTradeDesc());
			}else{
				resonse.setResultCode(String.valueOf(result.getTradeSataus()));
				resonse.setResultMsg(result.getTradeDesc());
			}
			break;
		case TRAN_BANK_TO_BANLANCE:
			result = innerCharge(orderTransferDO,gateWayChannelId,routeNo);
			if(resolveResult(result)){
				c2cTansfer(orderTransferDO,true);
				callBack(tradeOrderId, TransferOrderState.TRAN_STATUS_SUCCESS,"SUCCESS");
				updateTranOrderState(tradeOrderId, TransferOrderState.TRAN_STATUS_SUCCESS);
				resonse.setResultCode(String.valueOf(PayFlowState.SUCCESS.getCode()));
				resonse.setResultMsg(PayFlowState.SUCCESS.getDesc());
			}else{
				resonse.setResultCode(String.valueOf(result.getTradeSataus()));
				resonse.setResultMsg(result.getTradeDesc());
			}
			break;

		default:
			break;
		}
		resonse.setTradeOrderId(tradeOrderId);
		return resonse;	
	}
	
	/**
	 * 充值
	 * @param orderTransferDO
	 * @param routeNo   支付渠道
	 * @return
	 */
	private PayCoreResult innerCharge(OrderTransferDO orderTransferDO,String gateWayChannelId,String routeNo){
		String tradeOrderId = orderTransferDO.getTransferOrderId();
		//映射表添加订单
		String mappingOrderId = orderMappingService.addMappingOrder(orderTransferDO.getTransferOrderId(), (byte)PayFlowType.PAY.getCode());
		
		TradeInfo tradeInfo = new TradeInfo();
		
		tradeInfo.setAmount(orderTransferDO.getTransferAmount().intValue());		
		tradeInfo.setGoodsDetail("账户转账业务【内部支付】");		
		tradeInfo.setGoodsName("账户转账业务【内部支付】");		
		tradeInfo.setNotifyUrl(null);		
		tradeInfo.setRemark("账户转账业务【内部支付】");		
		tradeInfo.setReturnUrl(null);
		tradeInfo.setBankId(payerBindCardInfo.getBankId());
		tradeInfo.setFeeAmount(0);
		tradeInfo.setOrderType(TradeOrderType.TRANSFER_ORDER);
		tradeInfo.setOriginOrderNo(tradeOrderId);
		tradeInfo.setPassCipherPay(this.isPassClipherPay);
		tradeInfo.setTradeOrderId(mappingOrderId);
		tradeInfo.setGateWayChannelId(gateWayChannelId);
		PayCoreAccountInfo payerAccount = new PayCoreAccountInfo();	
		
		
		payerAccount.setPayerActNo(payerActInfo.getActNo());
		payerAccount.setPayerUserType(payerActInfo.getUserType());
		payerAccount.setPayerActType(UserActType.valueOf(payerActInfo.getActType()));
		payerAccount.setPayerUserId(payerActInfo.getUserId());

		
		if (payerBindCardInfo != null) {
			payerAccount.setBankAct(payerBindCardInfo.getCardNo());
			payerAccount.setBankId(payerBindCardInfo.getBankId());
			payerAccount.setCardType(CardType.valueOf(payerBindCardInfo.getCardType()));
			payerAccount.setIdentityType(IdCardType.valueOf(payerBindCardInfo.getIdentityType()));
			payerAccount.setIdentityNo(payerBindCardInfo.getIdentityNo());
			payerAccount.setMobile(payerBindCardInfo.getMobileNo());
			payerAccount.setRealName(payerBindCardInfo.getRealName());
			
			if(CardType.CARD_CREDIT.getValue() == payerBindCardInfo.getCardType()){
				payerAccount.setBankActCvv(payerBindCardInfo.getCardCvv());
				payerAccount.setBankActExpire(payerBindCardInfo.getExpireDate());
			}
			//payerAccount.setBankActName();
			payerAccount.setBankName(payerBindCardInfo.getBankName());
			payerAccount.setBankProvince(payerBindCardInfo.getCardProvince());
			payerAccount.setCardActType(CardActType.valueOf(payerBindCardInfo.getCardActType()));
		}
		tradeInfo.setBusinessType(orderTransferDO.getBusinessType());
		updateBusinessID(orderTransferDO.getTransferOrderId(), TransferBusinessID.CHARGE, BaseBusinessStatus.PAYING, "PAYING");
		
		if(JFUtils.isJFChannel(orderTransferDO.getPlatChannelId()) && StringUtil.isBlank(routeNo)){
			String jfRouteNo = JFUtils.getJfDefaultRouteNo(1);
			tradeInfo.setRouteNo(jfRouteNo);
		}else if(StringUtil.isNotBlank(routeNo)){
			tradeInfo.setRouteNo(routeNo);
		}
		
		
		PayCoreResult result = payCoreService.pay(payerAccount, tradeInfo, "tradeTransferSrervice");
		
		//wbank  免短信快捷支付 同步回调、异步回调同时收到  必须加锁
		PayFlowState payFlowState = PayFlowState.valueOf(result.getTradeSataus());
		if(payFlowState == PayFlowState.SUCCESS){
			lockRedisDAO.lockOrder(tradeOrderId+"charge", "success");
		}
		
		
		updatePayChannelId(orderTransferDO, result.getChannelId());
		
		return result;
	}
	
	/**
	 * 
	 * @param orderTransferDO
	 * @param netFee true需要扣除手续费  false不扣除手续费
	 */
	private void c2cTansfer(OrderTransferDO orderTransferDO,boolean netFee){
		String mappingOrderId = orderMappingService.addMappingOrder(orderTransferDO.getTransferOrderId(), (byte)TradeOrderType.TRANSFER_ORDER.getCode());
		PayCoreTransferReq req = new PayCoreTransferReq();
		req.setAmount(orderTransferDO.getTransferAmount());
		if(netFee){
			req.setFeeAmount(orderTransferDO.getTransferFee());
		}else{
			req.setFeeAmount(0);
		}
		
		UserActDO payerActInfo = actService.findUserAct(orderTransferDO.getPayerUserAct());
		UserActDO payeeActInfo = actService.findUserAct(orderTransferDO.getPayeeUserAct());
		
		
		req.setAttach("用户【"+orderTransferDO.getPayerUserId()+"】转账【"+orderTransferDO.getPayAmount()+"】到用户【"+orderTransferDO.getPayeeUserId()+"】");
		req.setOrderId(mappingOrderId);
		req.setOriginOrderId(orderTransferDO.getTransferOrderId());
		req.setPayeeActNo(payeeActInfo.getActNo());
		req.setPayeeUserType(payeeActInfo.getUserType());
		req.setPayeeActType(UserActType.valueOf(payeeActInfo.getActType()));
		req.setPayeeUserId(payeeActInfo.getUserId());
		
		req.setPayerActNo(payerActInfo.getActNo());
		req.setPayerUserType(payerActInfo.getUserType());
		req.setPayerActType(UserActType.valueOf(payerActInfo.getActType()));
		req.setPayerUserId(payerActInfo.getUserId());
		
		req.setTradeOrderType(TradeOrderType.TRANSFER_ORDER);
		
		req.setBusinessType(orderTransferDO.getBusinessType());
		try {
			payCoreService.balanceTransfer(req );
			updateBusinessID(orderTransferDO.getTransferOrderId(), TransferBusinessID.PERSON2PERSON, BaseBusinessStatus.SUCCESS, "SUCESS");
		} catch (Exception e) {
			updateBusinessID(orderTransferDO.getTransferOrderId(), TransferBusinessID.PERSON2PERSON, BaseBusinessStatus.FAILED, e.getMessage());
			throw new BusinessException(e.getMessage());
		}
	}
	//c2c退款转账
	private void c2cRefundTansfer(OrderTransferDO orderTransferDO){
		String mappingOrderId = orderMappingService.addMappingOrder(orderTransferDO.getTransferOrderId(), (byte)TradeOrderType.TRANSFER_ORDER.getCode());
		PayCoreTransferReq req = new PayCoreTransferReq();
//		UserActDO payerActInfo = getPayActInfo(orderTransferDO.getPayerUserId(), orderTransferDO.getPlatChannelId(),true);
//		UserActDO payeeActInfo = getPayActInfo(orderTransferDO.getPayeeUserId(), orderTransferDO.getPlatChannelId(),false);
		UserActDO payerActInfo = actService.findUserAct(orderTransferDO.getPayerUserAct());
		UserActDO payeeActInfo = actService.findUserAct(orderTransferDO.getPayeeUserAct());
		
		req.setAmount(orderTransferDO.getTransferAmount());
		req.setFeeAmount(0);
		req.setAttach("用户【"+orderTransferDO.getPayerUserId()+"】转账【"+orderTransferDO.getPayAmount()+"】到用户【"+orderTransferDO.getPayeeUserId()+"】");
		req.setOrderId(mappingOrderId);
		req.setOriginOrderId(orderTransferDO.getTransferOrderId());
		req.setPayeeActNo(payerActInfo.getActNo());
		req.setPayeeUserType(payerActInfo.getUserType());
		req.setPayeeActType(UserActType.valueOf(payerActInfo.getActType()));
		req.setPayeeUserId(payerActInfo.getUserId());
		
		req.setPayerActNo(payeeActInfo.getActNo());
		req.setPayerUserType(payeeActInfo.getUserType());
		req.setPayerActType(UserActType.valueOf(payeeActInfo.getActType()));
		req.setPayerUserId(payeeActInfo.getUserId());
		
		req.setTradeOrderType(TradeOrderType.TRANSFER_ORDER);
		req.setBusinessType(orderTransferDO.getBusinessType());
		try {
			payCoreService.balanceTransfer(req );
		} catch (Exception e) {
			updateBusinessID(orderTransferDO.getTransferOrderId(), TransferBusinessID.REFUND, BaseBusinessStatus.FAILED, e.getMessage());
			throw new BusinessException(e.getMessage());
		}
		
	}
	private PayCoreResult refundRecharge(OrderTransferDO orderTransferDO){
		String tradeOrderId = orderTransferDO.getTransferOrderId();
		String mappingOrderId = orderMappingService.getMappingOrderId(orderTransferDO.getTransferOrderId(), (byte)PayFlowType.PAY.getCode());
	
		//生成退款订单号
		String refundOrderId = billnoService.nextRefundNo();
		PayCoreRefund refund = new PayCoreRefund();
		refund.setAmount(orderTransferDO.getTransferAmount());
		refund.setAttach("转账失败,进行退款");
		refund.setFeeAmount(0);
		refund.setOriginChargeOrderId(mappingOrderId);
		//refund.setOriginTradeOrderId(mappingOrderId);
		refund.setRefundOrderId(refundOrderId);
		
		refund.setBusinessType(orderTransferDO.getBusinessType());
		PayCoreResult result = payCoreService.refund(refund , "tradeTransferSrervice");
		if(resolveResult(result)){
			updateBusinessID(orderTransferDO.getTransferOrderId(), TransferBusinessID.REFUND, BaseBusinessStatus.SUCCESS, "SUCESS");
			updateTranOrderState(tradeOrderId, TransferOrderState.TRAN_ORDER_FAIL_REFUND);
		}
		return result;
	}
	
	
	
	//代发
	private PayCoreResult innerWithDraw(OrderTransferDO orderTransferDO){
		String mappingOrderId = orderMappingService.addMappingOrder(orderTransferDO.getTransferOrderId(), (byte)TradeOrderType.TRANSFER_ORDER.getCode());
		
		PayCoreDistribute payCoreDistribute = new PayCoreDistribute();
		//UserActDO payeeActInfo = getPayActInfo(orderTransferDO.getPayeeUserId(), orderTransferDO.getPlatChannelId(),false);
		UserActDO payeeActInfo = actService.findUserAct(orderTransferDO.getPayeeUserAct());
		
		payCoreDistribute.setPayerActNo(payeeActInfo.getActNo());
		payCoreDistribute.setPayerUserType(payeeActInfo.getUserType());
		payCoreDistribute.setPayerActType(UserActType.valueOf(payeeActInfo.getActType()));
		payCoreDistribute.setPayerUserId(payeeActInfo.getUserId());
		
		Integer	cardActType = orderTransferDO.getPayeeCardActType().intValue();
		String	realName = orderTransferDO.getPayeeCardHolder();
		String cardProvince = orderTransferDO.getPayeeCardProvince();
		String cardCity = orderTransferDO.getPayeeCardCity();
		String cardNo = YHBFSensitiveEnc.sensitiveDec(orderTransferDO.getPayeeCardNo(),"cardno");
		CardActType paycardActType = null;
		if(cardActType != null){
			paycardActType = CardActType.valueOf(cardActType);
		}
		DistributeType distributeType = DistributeType.BANK;
		
		
		payCoreDistribute.setReferOrderId(mappingOrderId);
		payCoreDistribute.setTradeOrderType(TradeOrderType.TRANSFER_ORDER);
		
		payCoreDistribute.setPayeeUserId(orderTransferDO.getPayerUserId());
		payCoreDistribute.setPayeeUserType(payeeActInfo.getUserType());
		payCoreDistribute.setPayeeAccountId(cardNo);
		payCoreDistribute.setPayeeActType(UserActType.valueOf(payeeActInfo.getActType()));
		
		
		payCoreDistribute.setAmount(orderTransferDO.getTransferAmount());
		
		payCoreDistribute.setDistributeType(distributeType);
		payCoreDistribute.setFeeAmount(orderTransferDO.getTransferFee());
		payCoreDistribute.setOriginOrderNo(orderTransferDO.getTransferOrderId());
		
		
		payCoreDistribute.setAttach("用户【"+orderTransferDO.getPayerUserId()+"】代发【"+orderTransferDO.getPayAmount()+"】到用户【"+orderTransferDO.getPayeeUserId()+"】");
		payCoreDistribute.setRealName(realName);
		payCoreDistribute.setCardActType(paycardActType );
		payCoreDistribute.setCardProvince(cardProvince);
		payCoreDistribute.setCardCity(cardCity);
		
		payCoreDistribute.setBusinessType(orderTransferDO.getBusinessType());
		updateBusinessID(orderTransferDO.getTransferOrderId(), TransferBusinessID.DISTRIBUTE, BaseBusinessStatus.PAYING, "PAYING");
		PayCoreResult result = payCoreService.distribute(payCoreDistribute , "tradeTransferSrervice");
		
		updatePayChannelId(orderTransferDO, result.getChannelId());
		
		return result;
	}
	
	

	@Override
	void handerPayCoreResult() {
		
		
	}
	@Override
	public void callPayResult(PayCoreTradeInfo tradeInfo) {
		Log.info("call back start, tradeInfo:"+JSONObject.toJSONString(tradeInfo));
		
		String mappingOrderId = tradeInfo.getReferOrderId();
		
		//映射表反查订单
		String tradeOrderId = orderMappingService.getTradeOrderId(mappingOrderId);
		
		String payCoreOrderId = tradeInfo.getPayCoreOrderId();
		PayFlowState payFlowState = tradeInfo.getPayFlowState();
		TradeOrderType tradeOrderType = tradeInfo.getTradeOrderType();  
		PayFlowType payFlowType = tradeInfo.getPayFlowType();
	    String payeeUserId = tradeInfo.getPayeeUserId();
	    int payeeUserType = tradeInfo.getPayeeUserType(); 
	    String payerUserId = tradeInfo.getPayerUserId();
		int payerUserType = tradeInfo.getPayerUserType();
		long amount = tradeInfo.getAmount();
		
		
		OrderTransferDO orderTransferDO = orderTransferMysqlDAO.findById(tradeOrderId);
		if(orderTransferDO == null){
			Log.info("订单信息错误,无此订单");
			return;
		}
		byte tranferType = orderTransferDO.getTransferType();
		TransferType tranType = TransferType.valueOf(tranferType);
		
		TransferOrderState transferOrderState = null;
		switch (payFlowState) {
		case SUCCESS:
			transferOrderState = TransferOrderState.TRAN_STATUS_SUCCESS;
			break;
		case FAIL:
			transferOrderState = TransferOrderState.TRAN_STATUS_FAIL;		
			break;
		case EXCEPTION:
			transferOrderState = TransferOrderState.TRAN_STATUS_EXCEPTION;
			break;
		default:
			transferOrderState = TransferOrderState.TRAN_STATUS_EXCEPTION;
			break;
		}
		if(orderTransferDO.getOrderStatus() == TransferOrderState.TRAN_STATUS_SUCCESS.getCode()){
			Log.info("该订单已经完成支付,无需重复回调");
			return;
		}
		

		if(resolveTradeInfo(tradeInfo)){
			switch (payFlowType) {
			case DISTRIBUTE:
				if(tranType.equals(TransferType.TRAN_BANLANCE_TO_BANK) || tranType.equals(TransferType.TRAN_BANK_TO_BANK)){
					updateTranOrderState(tradeOrderId, transferOrderState);
					callBack(tradeOrderId, transferOrderState,tradeInfo.getPayFlowDesc());
				}
				break;
			case PAY:
				
				//wbank  免短信快捷支付 同步回调、异步回调同时收到  必须加锁
				boolean lockOrder = lockRedisDAO.lockOrder(tradeOrderId+"charge", "success");
				if(lockOrder){
					if(tranType.equals(TransferType.TRAN_BANK_TO_BANLANCE)){
						c2cTansfer(orderTransferDO,true);
						callBack(tradeOrderId, TransferOrderState.TRAN_STATUS_SUCCESS,"SUCCESS");
						updateTranOrderState(tradeOrderId, TransferOrderState.TRAN_STATUS_SUCCESS);
					}else if(tranType.equals(TransferType.TRAN_BANK_TO_BANK)){
						c2cTansfer(orderTransferDO,false);
						innerWithDraw(orderTransferDO);
					}
				}
				
				break;
			case REFUND:
				//退款成功  更新状态
				if(tranType.equals(TransferType.TRAN_BANK_TO_BANLANCE) || tranType.equals(TransferType.TRAN_BANK_TO_BANK)){
					updateBusinessID(orderTransferDO.getTransferOrderId(), TransferBusinessID.REFUND, BaseBusinessStatus.SUCCESS, "SUCESS");
					updateTranOrderState(tradeOrderId, TransferOrderState.TRAN_ORDER_FAIL_REFUND);
				}
			default:
				Log.info("业务类型错误,不允许回调,payFlowType:"+payFlowType);
				break;
			}
		}
		
	}

	private TransferType getTransferType(int payType,int receiverType){
		TransferType transferType = null;
		if(payType == 1 && receiverType == 1){
			transferType = TransferType.TRAN_BANLANCE_TO_BANLANCE;
			this.settleTradeType = SettleTradeType.TRANSFER_BERBON_BERBON;
		}else if(payType == 1 && receiverType == 2){
			transferType = TransferType.TRAN_BANLANCE_TO_BANK;
			this.settleTradeType = SettleTradeType.TRANSFER_BERBON_BANKCARD;
		}else if(payType == 2 && receiverType == 1){
			transferType = TransferType.TRAN_BANK_TO_BANLANCE;
			this.settleTradeType = SettleTradeType.TRANSFER_BANKCARD_BERBON;
		}else if(payType == 2 && receiverType == 2){
			transferType = TransferType.TRAN_BANK_TO_BANK;
			this.settleTradeType = SettleTradeType.TRANSFER_BANKCARD_BANKCARD;
		}
		this.transferType = transferType;
		return transferType;
	}
	
	
	private void updateTranOrderState(String transferOrderId,TransferOrderState state){
		 OrderTransferDO orderTransferDO = new OrderTransferDO();
		 orderTransferDO.setTransferOrderId(transferOrderId);
		 orderTransferDO.setOrderStatus((byte) state.getCode());
		 orderTransferDO.setOrderDesc(state.getDesc());
		 
		orderTransferMysqlDAO.update(orderTransferDO);
	}

	
	private boolean resolveTradeInfo(PayCoreTradeInfo tradeInfo){
		PayFlowState payFlowState = tradeInfo.getPayFlowState();
		String mappingOrderId = tradeInfo.getReferOrderId();
		//映射表反查订单
		String referOrderId = orderMappingService.getTradeOrderId(mappingOrderId);
		
		
		//批量转账
		PayFlowType payFlowType = tradeInfo.getPayFlowType();
		boolean personPayflag = false;
		if(payFlowType.equals(PayFlowType.BATCH_TRASFER)){
			OrderTransferDO orderTransferDO = orderTransferMysqlDAO.findById(referOrderId);
			List<PayCoreTransferResult> transferResultList = tradeInfo.getBatchTransferResult();
			for (PayCoreTransferResult payCoreTransferResult : transferResultList){
				if(!payCoreTransferResult.getTradeSataus().equals(PayFlowState.SUCCESS)){
					payFlowState = payCoreTransferResult.getTradeSataus();
					break;
				}else if(payCoreTransferResult.getPayeeUserId().equals(orderTransferDO.getPayeeUserId()) && 
						payCoreTransferResult.getTradeSataus().equals(PayFlowState.SUCCESS)){
					//批量转账转给用户为成功          回调成功
					personPayflag = true;
				}
			}
			
			
		}
		
		
		
		
		
		
		if(payFlowState != PayFlowState .SUCCESS){
			if(payFlowType.equals(PayFlowType.BATCH_TRASFER) && personPayflag){
				//批量转账转给用户为成功          回调成功
				updateTranOrderState(referOrderId, TransferOrderState.TRAN_STATUS_EXCEPTION);
				updateBusinessID(referOrderId, null, BaseBusinessStatus.EXCEPTION,tradeInfo.getPayFlowDesc());
				callBack(referOrderId, Constance.TransferOrderState.TRAN_STATUS_SUCCESS,tradeInfo.getPayFlowDesc());
			}else{
				if(payFlowState == PayFlowState.FAIL){
					updateTranOrderState(referOrderId, TransferOrderState.TRAN_STATUS_FAIL);
					updateBusinessID(referOrderId, null, BaseBusinessStatus.FAILED,tradeInfo.getPayFlowDesc());
					callBack(referOrderId, Constance.TransferOrderState.TRAN_STATUS_FAIL,tradeInfo.getPayFlowDesc());
				}else if(payFlowState == PayFlowState.EXCEPTION){
					updateTranOrderState(referOrderId, TransferOrderState.TRAN_STATUS_EXCEPTION);
					updateBusinessID(referOrderId, null, BaseBusinessStatus.EXCEPTION,tradeInfo.getPayFlowDesc());
					callBack(referOrderId, Constance.TransferOrderState.TRAN_STATUS_EXCEPTION,tradeInfo.getPayFlowDesc());
				}else{
					updateTranOrderState(referOrderId, TransferOrderState.TRAN_STATUS_EXCEPTION);
					updateBusinessID(referOrderId, null, BaseBusinessStatus.EXCEPTION,tradeInfo.getPayFlowDesc());
					callBack(referOrderId, Constance.TransferOrderState.TRAN_STATUS_EXCEPTION,tradeInfo.getPayFlowDesc());
				}
			}
			return false;
		}else{
			return true;
		}
	}
	
	
	//通知业务系统
	@Async
	private void callBack(String transferOrderId,TransferOrderState state,String orderDesc){
		Date payTime = new Date();
		OrderTransferDO orderTransferDO = new OrderTransferDO();
		orderTransferDO.setTransferOrderId(transferOrderId);
		orderTransferDO.setOrderStatus((byte) state.getCode());
		orderTransferDO.setPayTime(payTime);
		orderTransferMysqlDAO.update(orderTransferDO);
		orderTransferDO = orderTransferMysqlDAO.findById(transferOrderId);
		//通知业务系统
		CallBackOrderState callBackOrderState = null;
		if(state.equals(TransferOrderState.TRAN_STATUS_SUCCESS)){
			//成功通知风控系统
			boolean flag = lockRedisDAO.lockOrder(transferOrderId, "success");
			if (flag) {
				TranType tradeType = null;
				byte tranferType = orderTransferDO.getTransferType();
				TransferType tranType = TransferType.valueOf(tranferType);
				TradeType tType = null;
				if(tranType.equals(TransferType.TRAN_BANLANCE_TO_BANLANCE)){
					tradeType = TranType.TRANSFER_BERBON_BERBON;
					tType = TradeType.TRANSFER_BERBON_BERBON;
				}else if(tranType.equals(TransferType.TRAN_BANLANCE_TO_BANK)){
					tradeType = TranType.TRANSFER_BERBON_BANKCARD;
					tType = TradeType.TRANSFER_BERBON_BANKCARD;
				}else if(tranType.equals(TransferType.TRAN_BANK_TO_BANLANCE)){
					tradeType = TranType.TRANSFER_BANKCARD_BERBON;
					tType = TradeType.TRANSFER_BANKCARD_BERBON;
				}else if(tranType.equals(TransferType.TRAN_BANK_TO_BANK)){
					tradeType = TranType.TRANSFER_BANKCARD_BANKCARD;
					tType = TradeType.TRANSFER_BANKCARD_BANKCARD;
				}
				
				boolean isNoUsePwd = (int)orderTransferDO.getIsUsePwd() == 1 ? true : false;
//				riskControlService.updateUserRiskData(orderTransferDO.getPayerUserId() , tradeType,orderTransferDO.getTransferAmount(),isNoUsePwd);
			
				this.newupdateRisk(tType, orderTransferDO.getOrderId(), orderTransferDO.getPlatChannelId(), 
						orderTransferDO.getBusinessType(), null, orderTransferDO.getPayerUserId(), 
						orderTransferDO.getPayeeUserId(), orderTransferDO.getPayAmount().intValue(), 
						orderTransferDO.getPayChannelId(), orderTransferDO.getSourceIp(), null, isNoUsePwd,orderTransferDO.getAddTime());
			}
			
			
			callBackOrderState = CallBackOrderState.SUCCESS;
		}else if(state.equals(TransferOrderState.TRAN_STATUS_FAIL)){
			callBackOrderState = CallBackOrderState.FAIL;
		}else if(state.equals(TransferOrderState.TRAN_STATUS_EXCEPTION)){
			callBackOrderState = CallBackOrderState.EXCEPTION;
		}else{
			throw new BusinessException("非法的业务回调，当前订单状态不允许回调！ transferOrderState:"+state);
		}
		
		CallBackInfo callBackInfo = new CallBackInfo();
		callBackInfo.setTradeOrderId(orderTransferDO.getTransferOrderId());
		callBackInfo.setOutOrderId(orderTransferDO.getOrderId());
		callBackInfo.setNotfiyUrl(orderTransferDO.getNotifyUrl());
		callBackInfo.setReturnUrl(orderTransferDO.getReturnUrl());
		callBackInfo.setTotalFee(orderTransferDO.getTransferFee().intValue());
		callBackInfo.setPayAmount(orderTransferDO.getTransferAmount().intValue());
		callBackInfo.setAttach(orderTransferDO.getRemark());
		callBackInfo.setPayTime(payTime);
		callBackInfo.setTradeCrateTime(orderTransferDO.getAddTime());
		callBackInfo.setOrderType(TradeOrderType.TRANSFER_ORDER);
		callBackInfo.setOrderState(callBackOrderState);
		callBackInfo.setOrderDesc(orderDesc);
		callBackService.callBack(callBackInfo );
	}
	
	
	/**
	 * 查询子业务订单状态
	 * @param result
	 * @return
	 */
	private BaseBusinessStatus getBusinessStatus(PayCoreResult result){
		PayFlowState payFlowState = PayFlowState.valueOf(result.getTradeSataus());
		String mappingOrderId = result.getReferOrderId();
		String referOrderId = null;
		if(payFlowState != PayFlowState.SUCCESS){
			//映射表反查订单
			referOrderId = orderMappingService.getTradeOrderId(mappingOrderId);
		}
		
		if(payFlowState == PayFlowState.SUCCESS ){
			return BaseBusinessStatus.SUCCESS;
		}else if(payFlowState == PayFlowState.PAYING ){
			return BaseBusinessStatus.PAYING;
		}else if(payFlowState == PayFlowState.FAIL){
			callBack(referOrderId, Constance.TransferOrderState.TRAN_STATUS_FAIL,result.getTradeDesc());
			return BaseBusinessStatus.FAILED;
		}else if(payFlowState == PayFlowState.EXCEPTION){
			callBack(referOrderId, Constance.TransferOrderState.TRAN_STATUS_EXCEPTION,result.getTradeDesc());
			return BaseBusinessStatus.EXCEPTION;
		}else if(payFlowState == null){
			callBack(referOrderId, Constance.TransferOrderState.TRAN_STATUS_EXCEPTION,result.getTradeDesc());
			return BaseBusinessStatus.EXCEPTION;
		}else{
			return BaseBusinessStatus.EXCEPTION;
		}
	}
	/**
	 * 异常或者失败更新订单状态
	 * 回调
	 * @param baseBusinessStatus
	 * @param transferOrderId
	 */
	private void updateStateNotSuccess(BaseBusinessStatus baseBusinessStatus,String transferOrderId,String orderDesc){
		TransferOrderState transferOrderState = null;
		if(baseBusinessStatus.equals(BaseBusinessStatus.SUCCESS) || baseBusinessStatus.equals(BaseBusinessStatus.PAYING)){
			return;
		}else if(baseBusinessStatus.equals(BaseBusinessStatus.FAILED)){
			transferOrderState = TransferOrderState.TRAN_STATUS_FAIL;
		}else if(baseBusinessStatus.equals(BaseBusinessStatus.EXCEPTION)){
			transferOrderState = TransferOrderState.TRAN_STATUS_EXCEPTION;
		}else{
			transferOrderState = TransferOrderState.TRAN_STATUS_EXCEPTION;
		}
		OrderTransferDO orderTransferDO = new OrderTransferDO();
		orderTransferDO.setTransferOrderId(transferOrderId);
		orderTransferDO.setOrderStatus((byte) transferOrderState.getCode());
		orderTransferDO.setOrderDesc(transferOrderState.getDesc());
		orderTransferMysqlDAO.update(orderTransferDO);
		callBack(transferOrderId, transferOrderState,orderDesc);
	}
	private void updateBusinessID(OrderTransferDO orderTransferDO,TransferBusinessID transferBusinessID,PayCoreResult result){
		//获取子业务订单状态
		BaseBusinessStatus busStatus = getBusinessStatus(result);
		//子业务失败或异常更新订单状态
		updateStateNotSuccess(busStatus, orderTransferDO.getTransferOrderId(),result.getTradeDesc());
		//更新子业务编号、状态
		OrderTransferDO orderTransferDO2 = new OrderTransferDO();
		orderTransferDO2.setTransferOrderId(orderTransferDO.getTransferOrderId());
		orderTransferDO2.setBusniessId((byte)transferBusinessID.getValue());
		orderTransferDO2.setBusniessStatus((byte)busStatus.getValue());
		orderTransferMysqlDAO.update(orderTransferDO2);
	}
	private void updateBusinessID(String transferOrderId,TransferBusinessID transferBusinessID,BaseBusinessStatus businessStatus,String tradeDesc){
		//子业务失败或异常更新订单状态
		updateStateNotSuccess(businessStatus, transferOrderId,tradeDesc);
		OrderTransferDO orderTransferDO = new OrderTransferDO();
		orderTransferDO.setTransferOrderId(transferOrderId);
		//更新子业务编号、状态
		if(transferBusinessID != null){
			orderTransferDO .setBusniessId((byte)transferBusinessID.getValue());
		}
		if(businessStatus != null){
			orderTransferDO.setBusniessStatus((byte)businessStatus.getValue());
		}
		orderTransferMysqlDAO.update(orderTransferDO);
		
		
		
		
		
		//子业务成功  mq通知记录账单
		if(businessStatus.equals(BaseBusinessStatus.SUCCESS)){
			mqNotifyTradeSystem(transferOrderId, transferBusinessID, businessStatus, tradeDesc);
		}
		
		
	}
	
	@Async
	private void mqNotifyTradeSystem(String transferOrderId,TransferBusinessID transferBusinessID,BaseBusinessStatus businessStatus,String tradeDesc){
		OrderTransferDO orderTransferDO = orderTransferMysqlDAO.findById(transferOrderId);
		byte tranferType = orderTransferDO.getTransferType();
		TransferType tranType = TransferType.valueOf(tranferType);
		String platChannelId = orderTransferDO.getPlatChannelId();
		if(JFUtils.isJFChannel(platChannelId)){
			return;
		}
		
		switch (tranType) {
		case TRAN_BANLANCE_TO_BANLANCE:
			if(transferBusinessID == TransferBusinessID.PERSON2PERSON){
				sendTradeFlowMessage(orderTransferDO, 2, tradeDesc);
			}
			break;
			
		case TRAN_BANLANCE_TO_BANK:
			if(transferBusinessID == TransferBusinessID.PERSON2PERSON){
				sendTradeFlowMessage(orderTransferDO, 1, tradeDesc);
			}else if(transferBusinessID == TransferBusinessID.DISTRIBUTE){
				sendTradeFlowMessage(orderTransferDO, 2, tradeDesc);
			}		
			break;
					
		case TRAN_BANK_TO_BANLANCE:
			if(transferBusinessID == TransferBusinessID.CHARGE){
				sendTradeFlowMessage(orderTransferDO, 1, tradeDesc);
			}else if(transferBusinessID == TransferBusinessID.PERSON2PERSON){
				sendTradeFlowMessage(orderTransferDO, 2, tradeDesc);
			}
			break;
		case TRAN_BANK_TO_BANK:
			if(transferBusinessID == TransferBusinessID.CHARGE){
				sendTradeFlowMessage(orderTransferDO, 1, tradeDesc);
			}else if(transferBusinessID == TransferBusinessID.DISTRIBUTE){
				sendTradeFlowMessage(orderTransferDO, 2, tradeDesc);
			}
			break;

		default:
			break;
		}
	}
	
	private void updatePayChannelId(OrderTransferDO orderTransferDO,String payChannelId){
		OrderTransferDO orderTransferDO2 = new OrderTransferDO();
		orderTransferDO2.setTransferOrderId(orderTransferDO.getTransferOrderId());
		orderTransferDO2.setPayChannelId(payChannelId);
		orderTransferMysqlDAO.update(orderTransferDO2);
	}
	
	private boolean resolveResult(PayCoreResult result){
		PayFlowState payFlowState = PayFlowState.valueOf(result.getTradeSataus());
		String mappingOrderId = result.getReferOrderId();
		
		String referOrderId = null;
		//映射表反查订单
		referOrderId = orderMappingService.getTradeOrderId(mappingOrderId);
		if(payFlowState == PayFlowState.SUCCESS ){
			updateBusinessID(referOrderId, null, BaseBusinessStatus.SUCCESS, "SUCCESS");
			return true;
		}else if(payFlowState == PayFlowState.FAIL){
			updateTranOrderState(referOrderId, TransferOrderState.TRAN_STATUS_FAIL);
			callBack(referOrderId, Constance.TransferOrderState.TRAN_STATUS_FAIL,result.getTradeDesc());
		}else if(payFlowState == PayFlowState.EXCEPTION){
			updateTranOrderState(referOrderId, TransferOrderState.TRAN_STATUS_EXCEPTION);
			callBack(referOrderId, Constance.TransferOrderState.TRAN_STATUS_EXCEPTION,result.getTradeDesc());
		}else if(payFlowState == null){
			updateTranOrderState(referOrderId, TransferOrderState.TRAN_STATUS_EXCEPTION);
			callBack(referOrderId, Constance.TransferOrderState.TRAN_STATUS_EXCEPTION,result.getTradeDesc());
		}
		return false;
	}
	
	
	
	public TradeResponse refund(String tradeOrderId){
		OrderTransferDO orderTransferDO = orderTransferMysqlDAO.findById(tradeOrderId);
		String transferOrderId = orderTransferDO.getTransferOrderId();
		byte busniessId = orderTransferDO.getBusniessId();
		byte busniessStatus = orderTransferDO.getBusniessStatus();
		Byte orderStatus = orderTransferDO.getOrderStatus();
		if(orderStatus.intValue() == TransferOrderState.TRAN_STATUS_FAIL.getCode() && busniessStatus == BaseBusinessStatus.FAILED.getValue()){
			TransferBusinessID transferBusinessID = TransferBusinessID.valueOf(busniessId);
			byte tranferType = orderTransferDO.getTransferType();
			TransferType tranType = TransferType.valueOf(tranferType);
			boolean allowFlag = false;
			PayCoreResult refundResult = new PayCoreResult();
			TradeResponse response = new TradeResponse();
			switch (transferBusinessID) {
				case CHARGE:
					
					break;
				case DISTRIBUTE:
					if(tranType == TransferType.TRAN_BANLANCE_TO_BANK){
						//需要c2c转账的退款
						updateBusinessID(orderTransferDO.getTransferOrderId(), TransferBusinessID.REFUND, BaseBusinessStatus.PAYING, "PAYING");
						c2cRefundTansfer(orderTransferDO);
						updateBusinessID(orderTransferDO.getTransferOrderId(), TransferBusinessID.REFUND, BaseBusinessStatus.SUCCESS, "SUCESS");
						updateTranOrderState(transferOrderId, TransferOrderState.TRAN_ORDER_FAIL_REFUND);
						allowFlag = true;
						
						response.setResultCode(String.valueOf(PayFlowState.SUCCESS.getCode()));
						response.setResultMsg(PayFlowState.SUCCESS.getDesc());
					}else if(tranType == TransferType.TRAN_BANK_TO_BANK){
						//需要c2c转账的退款    A用户的充值退款
						updateBusinessID(orderTransferDO.getTransferOrderId(), TransferBusinessID.REFUND, BaseBusinessStatus.PAYING, "PAYING");
						c2cRefundTansfer(orderTransferDO);
						
						refundResult = refundRecharge(orderTransferDO);
						allowFlag = true;
						
						response.setResultCode(String.valueOf(refundResult.getTradeSataus()));
						response.setResultMsg(refundResult.getTradeDesc());
					}
					break;
				case PERSON2PERSON:
					if(tranType == TransferType.TRAN_BANK_TO_BANLANCE){
						//需要A用户的充值退款
						refundResult = refundRecharge(orderTransferDO);
						allowFlag = true;
						
						response.setResultCode(String.valueOf(refundResult.getTradeSataus()));
						response.setResultMsg(refundResult.getTradeDesc());
					}
					break;
				default:
					break;
			}
			if(allowFlag == false){
				throw new BusinessException("该订单状态不允许退款");
			}
			return response;
		}else{
			throw new BusinessException("该订单状态不允许退款");
		}
	}
	
	
	public TradeResponse reSubOrder(String tradeOrderId){
		OrderTransferDO orderTransferDO = orderTransferMysqlDAO.findById(tradeOrderId);
		byte busniessId = orderTransferDO.getBusniessId();
		byte busniessStatus = orderTransferDO.getBusniessStatus();
		Byte orderStatus = orderTransferDO.getOrderStatus();
		if(orderStatus.intValue() == TransferOrderState.TRAN_STATUS_FAIL.getCode() && busniessStatus == BaseBusinessStatus.FAILED.getValue()){
			TransferBusinessID transferBusinessID = TransferBusinessID.valueOf(busniessId);
			byte tranferType = orderTransferDO.getTransferType();
			TransferType tranType = TransferType.valueOf(tranferType);
			boolean allowFlag = false;
			TradeResponse resonse = new TradeResponse();
			PayCoreResult withdrawresult = new PayCoreResult();
			switch (transferBusinessID) {
				case CHARGE:
					
					break;
				case DISTRIBUTE:
					if(tranType == TransferType.TRAN_BANLANCE_TO_BANK || tranType == TransferType.TRAN_BANK_TO_BANK){
						allowFlag = true;
						withdrawresult = innerWithDraw(orderTransferDO);
						resonse.setResultCode(String.valueOf(withdrawresult.getTradeSataus()));
						resonse.setResultMsg(withdrawresult.getTradeDesc());
					}
					
					break;
				case PERSON2PERSON:
					if(tranType == TransferType.TRAN_BANK_TO_BANLANCE){
						c2cTansfer(orderTransferDO,true);
						resonse.setResultCode(String.valueOf(PayFlowState.SUCCESS.getCode()));
						resonse.setResultMsg(PayFlowState.SUCCESS.getDesc());
					}else if(tranType == TransferType.TRAN_BANK_TO_BANK){
						c2cTansfer(orderTransferDO,false);
						withdrawresult = innerWithDraw(orderTransferDO);
						resonse.setResultCode(String.valueOf(withdrawresult.getTradeSataus()));
						resonse.setResultMsg(withdrawresult.getTradeDesc());
					}
					break;
				default:
					break;
			}
			if(allowFlag == false){
				throw new BusinessException("该订单状态不允许退款");
			}
			return resonse;
		}else{
			throw new BusinessException("该订单状态不允许退款");
		}
	}
	
	private boolean sendTradeFlowMessage(TradeFlowMessage message) {
		String json = JSONObject.toJSONString(message);
		mqMessageService.sendTradeFlowMsg(json);
		return true;
	}
	
	/**
	 * 
	 * @param orderTransferDO
	 * @param innerState  1:支付者扣款成功,2:交易成功,3:交易失败
	 */
	private void sendTradeFlowMessage(OrderTransferDO orderTransferDO,int innerState, String tradeDesc){
		//退款通知tradeCenter
		TradeMessageType tradeMessageType = TradeMessageType.TRANSFER;;
		String berbonAcc = orderTransferDO.getPayerUserId();
		String otherBerbonAcc = orderTransferDO.getPayeeUserId();
		long tradeAmount = orderTransferDO.getTransferAmount(); // 交易金额
		long fee = orderTransferDO.getTransferFee();// 手续费
		long receiveAmount = orderTransferDO.getPayAmount();// 实际到账金额
		String tradeOrderNo = orderTransferDO.getOrderId();// 业务订单号
		String payOrderNo = orderTransferDO.getTransferOrderId();// 支付订单号
		
		TradeFlowMessage successMessage = new TradeFlowMessage();
		switch (innerState) {
		case 1:
			setPayTypeByBindNo(successMessage, orderTransferDO.getPayerBindNo(), orderTransferDO.getPayerUserId());
			break;
		case 2:
			String tmpBerbonAcc = berbonAcc;
			berbonAcc = otherBerbonAcc;
			otherBerbonAcc = tmpBerbonAcc;
			
			setPayTypeByBindNo(successMessage, orderTransferDO.getPayerBindNo(), orderTransferDO.getPayerUserId());
			break;
		case 3:
			receiveAmount = tradeAmount;
			fee = 0;
			tradeMessageType = TradeMessageType.REFUND;
			break;
		default:
			return;
		}
		
		successMessage.setTradeType(tradeMessageType.getCode());
		successMessage.setBerbonAcc(berbonAcc);
		successMessage.setOtherBerbonAcc(otherBerbonAcc);
		successMessage.setBusinessType(orderTransferDO.getBusinessType());
		successMessage.setTradeAmount(tradeAmount);
		successMessage.setReceiveAmount(receiveAmount);
		successMessage.setPayOrderNo(payOrderNo);
		successMessage.setTradeOrderNo(tradeOrderNo);
		successMessage.setFee(fee);
		successMessage.setInnerState(innerState);
		successMessage.setTradeDesc(tradeDesc);
		
		sendTradeFlowMessage(successMessage);
		
		String tmpBerbon = berbonAcc;
		successMessage.setBerbonAcc(successMessage.getOtherBerbonAcc());
		successMessage.setOtherBerbonAcc(tmpBerbon);
		sendTradeFlowMessage(successMessage);
	}
	
	private void setPayTypeByBindNo(TradeFlowMessage tradeMessage,
			String bindNo,String payerUserId) {
		String payType = null;
		if(StringUtils.isNotBlank(bindNo)) {
			UserBindCardDO userBindCardDO = accountService.findUserBindInfoIgnoreState(bindNo, payerUserId, BindCardType.BIND_QUICK_PAY);
			String cardNo = YHBFSensitiveEnc.sensitiveDec(userBindCardDO.getCardNo(), "cardno");
			cardNo = cardNo.substring(cardNo.length() - 4, cardNo.length());
			payType = userBindCardDO.getBankName() + "(" + cardNo + ")";
		} else {
			payType = "倍棒余额";
		}
		
		tradeMessage.setPayType(payType);
	}
}
